package com.farm.learn.service.impl;

import com.farm.learn.domain.ClassHour;
import com.farm.learn.domain.Classt;
import com.farm.learn.domain.MajorClass;
import com.farm.learn.domain.UserClass;
import com.farm.learn.domain.UserHour;
import com.farm.learn.domain.ex.ClassLearnView;
import com.farm.learn.domain.ex.HourView;
import com.farm.learn.domain.ex.MajorView;
import com.farm.learn.enums.ClassDifficulty;
import com.farm.core.time.TimeTool;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.farm.learn.dao.UserclassDaoInter;
import com.farm.learn.dao.UserhourDaoInter;
import com.farm.learn.service.ClasshourServiceInter;
import com.farm.learn.service.ClasstServiceInter;
import com.farm.learn.service.UserclassServiceInter;
import com.farm.sfile.WdapFileServiceInter;
import com.farm.sfile.enums.FileModel;
import com.farm.sfile.exception.FileExNameException;
import com.farm.wlp.events.EventHandLoader;
import com.farm.wuc.events.WucEventInfo;
import com.farm.wuc.events.WucEventModle;
import com.farm.wuc.events.WucEventRole;
import com.farm.wuc.events.WucEventUsers;
import com.farm.core.sql.query.DBRule;
import com.farm.core.sql.query.DBRuleList;
import com.farm.core.sql.query.DBSort;
import com.farm.core.sql.query.DataQuery;
import com.farm.core.sql.result.DataResult;
import com.farm.core.sql.result.ResultsHandle;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import com.farm.authority.FarmAuthorityService;
import com.farm.core.auth.domain.LoginUser;

/* *
 *功能：用户课程服务层实现类
 *详细：
 *
 *版本：v0.1
 *作者：FarmCode代码工程
 *日期：20150707114057
 *说明：
 */
@Service
public class UserclassServiceImpl implements UserclassServiceInter {
	@SuppressWarnings("unused")
	private static final Logger log = Logger.getLogger(UserclassServiceImpl.class);
	@Resource
	private UserclassDaoInter userclassDaoImpl;
	@Resource
	private UserhourDaoInter userhourDaoImpl;
	@Resource
	private ClasstServiceInter classTServiceImpl;
	@Resource
	private WdapFileServiceInter wdapFileServiceImpl;
	@Resource
	private ClasshourServiceInter classHourServiceImpl;

	@Override
	@Transactional
	public UserClass editUserclassEntity(UserClass entity, LoginUser user) {
		UserClass entity2 = userclassDaoImpl.getEntity(entity.getId());
		// entity2.setEuser(user.getId());
		// entity2.setEusername(user.getName());
		// entity2.setEtime(TimeTool.getTimeDate14());
		entity2.setNameback(entity.getNameback());
		entity2.setClassid(entity.getClassid());
		entity2.setPstate(entity.getPstate());
		entity2.setEtime(entity.getEtime());
		entity2.setStime(entity.getStime());
		entity2.setChoursid(entity.getChoursid());
		entity2.setUsetime(entity.getUsetime());
		entity2.setProcess(entity.getProcess());
		entity2.setId(entity.getId());
		userclassDaoImpl.editEntity(entity2);
		return entity2;
	}

	@Override
	@Transactional
	public void deleteUserclassEntity(String id, LoginUser user) {
		UserClass userclass = userclassDaoImpl.getEntity(id);
		userclassDaoImpl.deleteEntity(userclass);
		userhourDaoImpl.deleteEntitys(DBRuleList.getInstance().add(new DBRule("USERID", userclass.getUserid(), "="))
				.add(new DBRule("CLASSID", userclass.getClassid(), "=")).toList());
	}

	@Override
	@Transactional
	public UserClass getUserclassEntity(String id) {
		// TODO 自动生成代码,修改后请去除本注释
		if (id == null) {
			return null;
		}
		return userclassDaoImpl.getEntity(id);
	}

	@Override
	@Transactional
	public DataQuery createUserclassSimpleQuery(DataQuery query) {
		DataQuery dbQuery = DataQuery.init(query,
				"WLP_U_USERCLASS A LEFT JOIN ALONE_AUTH_USER B ON A.USERID = B.ID LEFT JOIN ALONE_AUTH_USERORG C ON C.USERID = B.ID LEFT JOIN ALONE_AUTH_ORGANIZATION D ON D.ID = C.ORGANIZATIONID LEFT JOIN WLP_L_CLASS E ON E.ID = A.CLASSID",
				"B. NAME AS NAME, A.USERID AS USERID, A.ID AS ID, A.NAMEBACK AS NAMEBACK, A.CLASSID AS CLASSID, A.PSTATE AS PSTATE, A.ETIME AS ETIME, A.LTIME AS LTIME, A.STIME AS STIME, A.CHOURSID AS CHOURSID, USETIME, PROCESS, LEARNTYPE, B.LOGINNAME AS LOGINNAME, D. NAME AS ORGNAME, E. NAME AS CLASSNAME ");
		return dbQuery;
	}

	@Override
	@Transactional
	public ClassLearnView getClassLearnView(String classid, LoginUser currentUser) {
		if (currentUser == null) {
			return ClassLearnView.getNone();
		}
		List<UserClass> userclasss = userclassDaoImpl.selectEntitys(DBRuleList.getInstance()
				.add(new DBRule("CLASSID", classid, "=")).add(new DBRule("USERID", currentUser.getId(), "=")).toList());
		if (userclasss.size() <= 0) {
			return ClassLearnView.getNone();
		}

		ClassLearnView view = ClassLearnView.getNone();
		view.setLearned(true);
		view.setUserclass(userclasss.get(0));
		view.setUserhours(
				userhourDaoImpl.selectEntitys(DBRuleList.getInstance().add(new DBRule("CLASSID", classid, "="))
						.add(new DBRule("USERID", currentUser.getId(), "=")).toList()));

		return view;
	}

	@Override
	@Transactional
	public HourView startLearnClass(String classid, String hourid, LoginUser currentUser) throws FileExNameException {
		if (currentUser == null) {
			throw new RuntimeException("学习课程时,用户不能为空!");
		}
		synchronized (currentUser.getId()) {
			UserClass userClass = userclassDaoImpl.getEntity(currentUser.getId(), classid);
			// 是否之前学习过课程
			if (userClass == null) {
				// 如果沒有学习过就加载第一个课时，同时生成学习记录
				Classt classt = classTServiceImpl.getClasstEntity(classid);
				if (classt.getJointype().equals("2")) {
					throw new RuntimeException("本课程无法自主学习，请联系管理员获取学习权限!");
				}
				userClass = new UserClass();
				userClass.setClassid(classid);
				if (StringUtils.isBlank(hourid)) {
					ClassHour hour = classTServiceImpl.getFirstHour(classid);
					userClass.setChoursid(hour.getId());
				} else {
					userClass.setChoursid(hourid);
				}
				// userClass.setEtime(etime);
				// userClass.setId(id);
				userClass.setNameback(classt.getName());
				userClass.setProcess(0);
				userClass.setLtime(TimeTool.getTimeDate14());
				userClass.setLearntype("1");
				userClass.setPstate("2");
				userClass.setStime(TimeTool.getTimeDate14());
				userClass.setUsetime(0);
				userClass.setUserid(currentUser.getId());
				userclassDaoImpl.insertEntity(userClass);
				// 记录开始学习课程事件
				runEvent(WucEventModle.CLASS_LEARN_S, userClass.getClassid(), null, currentUser);
			} else {
				userClass = userclassDaoImpl.getEntity(userClass.getId());
				userClass.setLtime(TimeTool.getTimeDate14());
				if (StringUtils.isNotBlank(hourid)) {
					// 如果用户指定了课程就将该课程作为当前课程
					userClass.setChoursid(hourid);
				}
				userclassDaoImpl.editEntity(userClass);
			}
			UserHour userHour = userhourDaoImpl.getEntity(currentUser.getId(), userClass.getChoursid());
			// 如果课时沒有学习过，就加载学习记录
			if (userHour == null) {
				userHour = new UserHour();
				userHour.setClassid(classid);
				// userHour.setEtime(etime);
				userHour.setHourid(userClass.getChoursid());
				userHour.setPstate("2");
				userHour.setStime(TimeTool.getTimeDate14());
				userHour.setLtime(TimeTool.getTimeDate14());
				userHour.setUserid(currentUser.getId());
				userhourDaoImpl.insertEntity(userHour);
				// 记录开始学习课时事件
				runEvent(WucEventModle.HOUR_LEARN_S, userClass.getClassid(), userHour.getHourid(), currentUser);
			}

			HourView hourview = classTServiceImpl.getHourView(userClass.getChoursid());

			return hourview;
		}
	}

	/**
	 * 记录事件(开始学习课程事件； 开始学习课时事件； 完成课程事件；)
	 * 
	 * @param modle
	 * @param classid
	 * @param currentUser
	 */
	private void runEvent(WucEventModle modle, String classid, String hourid, LoginUser currentUser) {
		try {
			String objid;
			String objTitle;
			String authorid;
			Classt classt = classTServiceImpl.getClasstEntity(classid);
			ClassHour hour = null;
			if (StringUtils.isNotBlank(hourid)) {
				hour = classHourServiceImpl.getClasshourEntity(hourid);
				objid = hour.getId();
				objTitle = hour.getTitle();
				authorid = hour.getCuser();
			} else {
				objid = classt.getId();
				objTitle = classt.getName();
				authorid = classt.getCuser();
			}
			WucEventInfo info = new WucEventInfo(objid, objTitle);
			if (hour != null) {
				// 有课时信息就添加课程信息(一般情况这时课时进行存入OBJid中
				info.addText1(classt.getId(), "课程ID");
				info.addText2(classt.getName(), "课程名称");
			}
			EventHandLoader.getHandler().runEvent(//
					modle, info,
					new WucEventUsers().addUser(WucEventRole.AUTHOR,
							FarmAuthorityService.getInstance().getUserById(authorid), null)
							.addUser(WucEventRole.OPRETOR, currentUser, null));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	@Transactional
	public void bindUserClass(String classid, String userid, LoginUser currentUser) throws FileExNameException {
		// 同一个用户同一时间只能进入一个，避免因为创建延迟导致的学习记录重复创建问题
		synchronized (userid) {
			UserClass userClass = userclassDaoImpl.getEntity(userid, classid);
			// 是否之前学习过课程
			if (userClass == null) {
				// 如果沒有学习过就加载第一个课时，同时生成学习记录
				Classt classt = classTServiceImpl.getClasstEntity(classid);
				userClass = new UserClass();
				userClass.setClassid(classid);
				ClassHour hour = classTServiceImpl.getFirstHour(classid);
				userClass.setChoursid(hour.getId());
				userClass.setNameback(classt.getName());
				userClass.setProcess(0);
				userClass.setLtime(TimeTool.getTimeDate14());
				userClass.setLearntype("2");
				userClass.setPstate("2");
				userClass.setStime(TimeTool.getTimeDate14());
				userClass.setUsetime(0);
				userClass.setUserid(userid);
				userclassDaoImpl.insertEntity(userClass);
			} else {
				throw new RuntimeException("用户已经绑定到课程，不能重复绑定");
			}
			UserHour userHour = userhourDaoImpl.getEntity(userid, userClass.getChoursid());
			// 如果学习过就加载之前未完成的课时，或者已经完成的下一节课时同时生成学习记录
			if (userHour == null) {
				userHour = new UserHour();
				userHour.setClassid(classid);
				// userHour.setEtime(etime);
				userHour.setHourid(userClass.getChoursid());
				userHour.setPstate("2");
				userHour.setStime(TimeTool.getTimeDate14());
				userHour.setLtime(TimeTool.getTimeDate14());
				userHour.setUserid(userid);
				userhourDaoImpl.insertEntity(userHour);
			}
		}
	}

	@Override
	@Transactional
	public DataResult getUserClasses(DataQuery query, LoginUser currentUser) throws SQLException {
		query.addRule(new DBRule("b.PSTATE", "1", "="));
		query.addSort(new DBSort("a.LTIME", "DESC"));
		query.addRule(new DBRule("a.USERID", currentUser.getId(), "="));
		DataQuery dbQuery = DataQuery.init(query,
				"WLP_U_USERCLASS a LEFT JOIN WLP_L_CLASS b ON a.CLASSID = b.id LEFT JOIN wlp_l_classhour c ON a.CHOURSID = c.id",
				"a.id as id,a.LEARNTYPE as LEARNTYPE,b.id as classid,c.id as hourid,b.IMGID AS IMGID, b. NAME AS NAME, a.NAMEBACK AS BNAME, a.PROCESS AS PROCESS, a.USETIME AS USETIME, c.TITLE AS HOURTITLE");
		DataResult result = dbQuery.search();
		result.runDictionary(ClassDifficulty.getMap(), "DIFFICULTY");
		result.runHandle(new ResultsHandle() {
			@Override
			public void handle(Map<String, Object> row) {
				if (row.get("IMGID") != null) {
					String url = wdapFileServiceImpl.getDownloadUrl((String) row.get("IMGID"), FileModel.IMG);
					row.put("IMGURL", url);
				}
			}
		});
		return result;
	}

	@Override
	@Transactional
	public String finishCurrentHour(String classid, LoginUser currentUser) {
		// 1获取当前课时
		UserClass userClass = userclassDaoImpl.getEntity(currentUser.getId(), classid);
		if (userClass == null) {
			throw new RuntimeException("当前用户未开始此课程学习!");
		}
		String currentHourid = userClass.getChoursid();
		// 2更新当前课时信息
		UserHour currenthour = userhourDaoImpl.getEntity(currentUser.getId(), currentHourid);

		if (currenthour != null && !currenthour.getPstate().equals("1")) {
			// 之前沒有完成课时，初次完成课时
			// 记录课时完成事件
			runEvent(WucEventModle.HOUR_LEARN_C, userClass.getClassid(), currenthour.getHourid(), currentUser);
		}

		currenthour.setPstate("1");
		currenthour.setEtime(TimeTool.getTimeDate14());
		currenthour.setLtime(TimeTool.getTimeDate14());
		userhourDaoImpl.editEntity(currenthour);
		// 3计算出下一个课时
		Set<String> completeHourids = userhourDaoImpl.getCompleteHourids(classid, currentUser.getId());
		ClassHour hour = classTServiceImpl.getNextHour(classid, currentHourid, completeHourids);
		// 4更新课程当前课时
		userClass.setChoursid(hour.getId());
		// 5计算课时完成百分比
		userClass.setProcess(getUserLearnProcess(classid, currentUser.getId()));
		if (userClass.getProcess() >= 100) {
			userClass.setPstate("3");
			userClass.setEtime(TimeTool.getTimeDate14());
			// 记录完成课程事件
			runEvent(WucEventModle.CLASS_LEARN_C, userClass.getClassid(), null, currentUser);
		}
		userclassDaoImpl.editEntity(userClass);
		return hour.getId();
	}

	/**
	 * 获得用户学习课程的百分比
	 * 
	 * @param classid
	 * @param userid
	 * @return
	 */
	private int getUserLearnProcess(String classid, String userid) {
		int allHournum = classTServiceImpl.getAllHoursNum(classid);
		Set<String> completeHourids = userhourDaoImpl.getCompleteHourids(classid, userid);
		int completeHournum = completeHourids.size();
		return completeHournum * 100 / allHournum;
	}

	@Override
	@Transactional
	public void refrashLearnStat(String userClassId) {
		UserClass userclass = userclassDaoImpl.getEntity(userClassId);
		userclass.setProcess(getUserLearnProcess(userclass.getClassid(), userclass.getUserid()));
		if (userclass.getProcess() >= 100) {
			userclass.setPstate("3");
			userclass.setEtime(TimeTool.getTimeDate14());
		} else {
			userclass.setPstate("2");
		}
		userclassDaoImpl.editEntity(userclass);
	}

	@Override
	@Transactional
	public void delUserClass(String classid, String userId) {
		List<UserClass> list = userclassDaoImpl.selectEntitys(DBRuleList.getInstance()
				.add(new DBRule("CLASSID", classid, "=")).add(new DBRule("USERID", userId, "=")).toList());
		for (UserClass uclass : list) {
			if (uclass.getLearntype().equals("2")) {
				throw new RuntimeException("请联系管理员从后台删除该记录!");
			}
		}
		userhourDaoImpl.deleteEntitys(DBRuleList.getInstance().add(new DBRule("CLASSID", classid, "="))
				.add(new DBRule("USERID", userId, "=")).toList());
		userclassDaoImpl.deleteEntitys(DBRuleList.getInstance().add(new DBRule("CLASSID", classid, "="))
				.add(new DBRule("USERID", userId, "=")).toList());
	}

	@Override
	@Transactional
	public int getUserCurrentClassNum(String userid) {
		return userclassDaoImpl.countEntitys(DBRuleList.getInstance().add(new DBRule("PSTATE", "2", "="))
				.add(new DBRule("USERID", userid, "=")).toList());
	}

	@Override
	@Transactional
	public DataResult learUsersQuery(DataQuery query) throws SQLException {
		query = DataQuery.init(query,
				"WLP_U_USERCLASS a LEFT JOIN ALONE_AUTH_USER b ON a.USERID = b.id LEFT JOIN ALONE_AUTH_USERORG c ON c.USERID = a.USERID LEFT JOIN alone_auth_organization d ON d.id = c.ORGANIZATIONID",
				"b. NAME AS USERNAME,d.NAME AS ORGNAME,a.PROCESS as PROCESS,a.STIME as STIME,a.ETIME as ETIME,a.LTIME as LTIME,a.PSTATE as LEARNSTATE");
		return query.search();
	}

	@Override
	@Transactional
	public void bingUserClasses(MajorView majorview, LoginUser currentUser) {
		for (MajorClass mclass : majorview.getClasses()) {
			if (currentUser != null) {
				mclass.setUserclass(userclassDaoImpl.getEntity(currentUser.getId(), mclass.getClassid()));
			}
			mclass.setReadable(classTServiceImpl.isReadAble(mclass.getClassid(), currentUser));
		}
	}
}